package com.rla.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.rla.common.core.page.TableDataInfo;
import com.rla.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rla.common.utils.SecurityUtils;
import com.rla.common.utils.StringUtils;
import com.rla.domain.EhsEverydayBloodGlucose;
import com.rla.domain.EhsEverydayWeight;
import com.rla.domain.bo.EhsEverydayBloodGlucoseBo;
import com.rla.domain.vo.EhsEverydayBloodGlucoseVo;
import com.rla.service.IBaseHealthTargetRuleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.rla.domain.bo.EhsEverydayBloodPressureBo;
import com.rla.domain.vo.EhsEverydayBloodPressureVo;
import com.rla.domain.EhsEverydayBloodPressure;
import com.rla.mapper.EhsEverydayBloodPressureMapper;
import com.rla.service.IEhsEverydayBloodPressureService;

import java.math.BigDecimal;
import java.util.*;

/**
 * 日常记录-血压记录Service业务层处理
 *
 * @author rla
 * @date 2025-09-11
 */
@RequiredArgsConstructor
@Service
public class EhsEverydayBloodPressureServiceImpl implements IEhsEverydayBloodPressureService {

    private final EhsEverydayBloodPressureMapper baseMapper;

    private final IBaseHealthTargetRuleService iBaseHealthTargetRuleService;

    /**
     * 查询日常记录-血压记录
     */
    @Override
    public EhsEverydayBloodPressureVo queryById(String id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询日常记录-血压记录列表
     */
    @Override
    public TableDataInfo<EhsEverydayBloodPressureVo> queryPageList(EhsEverydayBloodPressureBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<EhsEverydayBloodPressure> lqw = buildQueryWrapper(bo);
        Page<EhsEverydayBloodPressureVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询日常记录-血压记录列表
     */
    @Override
    public List<EhsEverydayBloodPressureVo> queryList(EhsEverydayBloodPressureBo bo) {
        LambdaQueryWrapper<EhsEverydayBloodPressure> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<EhsEverydayBloodPressure> buildQueryWrapper(EhsEverydayBloodPressureBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EhsEverydayBloodPressure> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getUserId()), EhsEverydayBloodPressure::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getMeasuredTime()), EhsEverydayBloodPressure::getMeasuredTime, bo.getMeasuredTime());
        lqw.eq(StringUtils.isNotBlank(bo.getSystolicPressure()), EhsEverydayBloodPressure::getSystolicPressure, bo.getSystolicPressure());
        lqw.eq(StringUtils.isNotBlank(bo.getDiastolicPressure()), EhsEverydayBloodPressure::getDiastolicPressure, bo.getDiastolicPressure());
        lqw.eq(StringUtils.isNotBlank(bo.getSphygmus()), EhsEverydayBloodPressure::getSphygmus, bo.getSphygmus());
        lqw.eq(StringUtils.isNotBlank(bo.getSourceType()), EhsEverydayBloodPressure::getSourceType, bo.getSourceType());
        lqw.like(StringUtils.isNotBlank(bo.getSourceName()), EhsEverydayBloodPressure::getSourceName, bo.getSourceName());
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceCode()), EhsEverydayBloodPressure::getDeviceCode, bo.getDeviceCode());
        lqw.eq(StringUtils.isNotBlank(bo.getIsLook()), EhsEverydayBloodPressure::getIsLook, bo.getIsLook());
        lqw.eq(StringUtils.isNotBlank(bo.getBusinessId()), EhsEverydayBloodPressure::getBusinessId, bo.getBusinessId());
        lqw.eq(StringUtils.isNotBlank(bo.getColor()), EhsEverydayBloodPressure::getColor, bo.getColor());
        lqw.eq(bo.getFgcCreatedate() != null, EhsEverydayBloodPressure::getFgcCreatedate, bo.getFgcCreatedate());
        lqw.eq(StringUtils.isNotBlank(bo.getFgcLastmodifier()), EhsEverydayBloodPressure::getFgcLastmodifier, bo.getFgcLastmodifier());
        lqw.eq(bo.getFgcLastmodifydate() != null, EhsEverydayBloodPressure::getFgcLastmodifydate, bo.getFgcLastmodifydate());
        lqw.eq(StringUtils.isNotBlank(bo.getFgcCreator()), EhsEverydayBloodPressure::getFgcCreator, bo.getFgcCreator());
        if (StringUtils.isNotBlank(bo.getTag())&&"正常".equals(bo.getTag())){
            lqw.eq(StringUtils.isNotBlank(bo.getTag()), EhsEverydayBloodPressure::getTag, bo.getTag());
        }else if (StringUtils.isNotBlank(bo.getTag()) && "异常".equals(bo.getTag())){
            lqw.and(StringUtils.isNotBlank(bo.getTag())&& "异常".equals(bo.getTag()), w -> {
                w.eq(EhsEverydayBloodPressure::getTag, "低血压").or().eq(EhsEverydayBloodPressure::getTag, "一级高血压").or().eq(EhsEverydayBloodPressure::getTag, "二级高血压").or().eq(EhsEverydayBloodPressure::getTag, "三级高血压");
            });
        }
        lqw.orderByDesc(EhsEverydayBloodPressure::getMeasuredTime);
        return lqw;
    }

    /**
     * 新增日常记录-血压记录
     */
    @Override
    public String insertByBo(EhsEverydayBloodPressureBo bo) {
        bo.setUserId(SecurityUtils.getUserId().toString());
        EhsEverydayBloodPressure add = BeanUtil.toBean(bo, EhsEverydayBloodPressure.class);
        validEntityBeforeSave(add);
        add.setCreateBy(SecurityUtils.getUserId().toString());
        add.setCreateTime(new Date());

        //TODO ui设计的规则有问题，应该逐级同时判断即可，后期优化
        Map<String, Object> resultMap = iBaseHealthTargetRuleService.calculateIndicators("血压", "27", Double.valueOf(bo.getSystolicPressure()));

        Map<String, Object> resultMap1 = iBaseHealthTargetRuleService.calculateIndicators("血压", "28", Double.valueOf(bo.getDiastolicPressure()));

        String systolicTag = resultMap.get("tag").toString();
        String systolicColor = resultMap.get("color").toString();

        String diastolicTag = resultMap.get("tag").toString();
        String diastolicColor = resultMap.get("color").toString();



        if ("正常".equals(systolicTag)) {
            if ("正常".equals(diastolicTag)){//收缩压正常，舒张压正常
                add.setTag(systolicTag);
                add.setColor(systolicColor);
            }else {//收缩压正常，舒张压异常
                add.setTag(diastolicTag);
                add.setColor(diastolicColor);
            }
        }else{//收缩压异常，舒张压正常
            if ("正常".equals(diastolicTag)){//收缩压异常，舒张压正常
                add.setTag(systolicTag);
                add.setColor(systolicColor);
            }else{//都不正常
                //TODO 随机取一个，后续再判断
                add.setTag(systolicTag);
                add.setColor(systolicColor);
            }
        }

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return add.getId();
    }

    /**
     * 修改日常记录-血压记录
     */
    @Override
    public Boolean updateByBo(EhsEverydayBloodPressureBo bo) {
        EhsEverydayBloodPressure update = BeanUtil.toBean(bo, EhsEverydayBloodPressure.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(EhsEverydayBloodPressure entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除日常记录-血压记录
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    // 常量定义
    private static final String NO_DATA_FLAG = "-";
    private static final String INCREASE_FLAG = "1";
    private static final String DECREASE_FLAG = "0";
    private static final int TEN_DAYS_OFFSET = -10;

    @Override
    public Map<String, Object> queryDateCompare(String id) {
        // 参数校验
        if (StringUtils.isBlank(id)) {
            throw new IllegalArgumentException("血压记录ID不能为空");
        }

        // 获取当前血压记录
        EhsEverydayBloodPressureVo currentRecord = baseMapper.selectVoById(id);
        if (currentRecord == null) {
            throw new IllegalArgumentException("未找到指定的血压记录");
        }

        String measuredTime = currentRecord.getMeasuredTime();
        String systolicPressure = currentRecord.getSystolicPressure();
        String diastolicPressure = currentRecord.getDiastolicPressure();

        Map<String, Object> result = new HashMap<>();

        // 处理最近一次记录比较
        processLastRecordComparison(measuredTime, systolicPressure, diastolicPressure, result);

        // 处理近10天记录比较
        processTenDaysComparison(measuredTime, systolicPressure, diastolicPressure, result);

        return result;
    }

    /**
     * 处理最近一次记录比较
     */
    private void processLastRecordComparison(String measuredTime, String systolicPressure, 
                                          String diastolicPressure, Map<String, Object> result) {
        Map<String, Object> lastRecord = baseMapper.queryDateCompare(measuredTime);
        
        if (ObjectUtil.isEmpty(lastRecord)) {
            setDefaultValues(result, "last");
            return;
        }

        String lastSystolic = lastRecord.get("systolicPressure").toString();
        String lastDiastolic = lastRecord.get("diastolicPressure").toString();
        String lastDate = lastRecord.get("measuredTimeFormat").toString();

        // 计算血压差值
        BloodPressureDiff systolicDiff = calculateBloodPressureDiff(systolicPressure, lastSystolic);
        BloodPressureDiff diastolicDiff = calculateBloodPressureDiff(diastolicPressure, lastDiastolic);

        // 设置结果
        result.put("lastSystolicDiff", systolicDiff.diff);
        result.put("lastDiastolicDiff", diastolicDiff.diff);
        result.put("lastDate", lastDate);
        result.put("lastSystolicFlag", systolicDiff.flag);
        result.put("lastDiastolicFlag", diastolicDiff.flag);
    }

    /**
     * 处理近10天记录比较
     */
    private void processTenDaysComparison(String measuredTime, String systolicPressure, 
                                       String diastolicPressure, Map<String, Object> result) {
        try {
            DateTime currentDate = DateUtil.parse(measuredTime);
            String tenDaysAgo = DateUtil.offsetDay(currentDate, TEN_DAYS_OFFSET).toDateStr();
            Map<String, Object> tenDaysRecord = baseMapper.queryDateCompare(tenDaysAgo);

            if (ObjectUtil.isEmpty(tenDaysRecord)) {
                setDefaultValues(result, "tenDays");
                return;
            }

            String tenDaysSystolic = tenDaysRecord.get("systolicPressure").toString();
            String tenDaysDiastolic = tenDaysRecord.get("diastolicPressure").toString();
            String tenDaysDate = tenDaysRecord.get("measuredTimeFormat").toString();

            // 计算血压差值
            BloodPressureDiff systolicDiff = calculateBloodPressureDiff(systolicPressure, tenDaysSystolic);
            BloodPressureDiff diastolicDiff = calculateBloodPressureDiff(diastolicPressure, tenDaysDiastolic);

            // 计算天数差
            long betweenDays = calculateDaysBetween(measuredTime, tenDaysRecord.get("measuredTime").toString());

            // 设置结果
            result.put("tenDaysSystolicDiff", systolicDiff.diff);
            result.put("tenDaysDiastolicDiff", diastolicDiff.diff);
            result.put("tenDaysDate", tenDaysDate);
            result.put("betweenDay", betweenDays);
            result.put("tenDaysSystolicFlag", systolicDiff.flag);
            result.put("tenDaysDiastolicFlag", diastolicDiff.flag);

        } catch (Exception e) {
            // 日期解析异常时设置默认值
            setDefaultValues(result, "tenDays");
        }
    }

    /**
     * 计算血压差值
     */
    private BloodPressureDiff calculateBloodPressureDiff(String currentPressure, String comparePressure) {
        try {
            BigDecimal current = new BigDecimal(currentPressure);
            BigDecimal compare = new BigDecimal(comparePressure);
            BigDecimal diff = current.subtract(compare);
            String flag = diff.compareTo(BigDecimal.ZERO) > 0 ? INCREASE_FLAG : DECREASE_FLAG;
            return new BloodPressureDiff(diff, flag);
        } catch (NumberFormatException e) {
            return new BloodPressureDiff(new BigDecimal(0), DECREASE_FLAG);
        }
    }

    /**
     * 计算两个日期之间的天数差
     */
    private long calculateDaysBetween(String dateStr1, String dateStr2) {
        try {
            Date date1 = DateUtil.parse(dateStr1);
            Date date2 = DateUtil.parse(dateStr2);
            return DateUtil.between(date1, date2, DateUnit.DAY);
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 设置默认值
     */
    private void setDefaultValues(Map<String, Object> result, String prefix) {
        result.put(prefix + "SystolicFlag", DECREASE_FLAG);
        result.put(prefix + "DiastolicFlag", DECREASE_FLAG);
        result.put(prefix + "SystolicDiff", NO_DATA_FLAG);
        result.put(prefix + "DiastolicDiff", NO_DATA_FLAG);
        result.put(prefix + "Date", NO_DATA_FLAG);
        
        if ("tenDays".equals(prefix)) {
            result.put("betweenDay", NO_DATA_FLAG);
        }
    }

    /**
     * 血压差值内部类
     */
    private static class BloodPressureDiff {
        final BigDecimal diff;
        final String flag;

        BloodPressureDiff(BigDecimal diff, String flag) {
            this.diff = diff;
            this.flag = flag;
        }
    }

    @Override
    public Map<String, Object> statisticsExce(EhsEverydayBloodGlucoseBo bo) {
        //正常异常数量统计
        String startDate = bo.getStartDate()+" 00:00:00";
        String endDate = bo.getEndDate()+" 23:59:59";
        List<Map<String, Object>> maps = baseMapper.statisticsExce(bo.getUserId(), startDate, endDate);
        Map<String, Object> map1 = new HashMap<>();
        if(ObjectUtil.isNotEmpty(maps)){
            for (Map<String, Object> map : maps) {
                map1.put(map.get("tag").toString(), map.get("num").toString());
            }
        }
        return map1;
    }

    @Override
    public List<Map<String, Object>> queryTrendList(EhsEverydayBloodPressureBo bo) {
        List<Map<String, Object>> list = new ArrayList<>();
//        DateUtil
        String startDate = bo.getStartDate()+" 00:00:00";
        String endDate = bo.getEndDate()+" 23:59:59";

        //趋势数据图表
        list = baseMapper.getTrendList(bo.getUserId(),startDate,endDate);

        return list;
    }

    @Override
    public Map<String, Object> healthReport(EhsEverydayBloodPressureBo bo) {
        String startDate = bo.getStartDate()+" 00:00:00";
        String endDate = bo.getEndDate()+" 23:59:59";
        Map<String, Object> healthReportCountMap = baseMapper.healthReport(bo.getUserId(), startDate, endDate);
        Map<String, Object> map1 = new HashMap<>();

        List<Map<String, Object>> maps = baseMapper.getTagCountStatistics(bo.getUserId(), startDate, endDate);
        if(ObjectUtil.isNotEmpty(maps)){
            for (Map<String, Object> map : maps) {
                map1.put(map.get("tagName").toString(), map.get("tagCount").toString());
            }
        }
        map1.put("count",ObjectUtil.isNotEmpty(healthReportCountMap.get("num"))? healthReportCountMap.get("num"):0 );
        map1.put("minSystolicValue",ObjectUtil.isNotEmpty(healthReportCountMap.get("min_systolic_value"))? healthReportCountMap.get("min_systolic_value"):0 );
        map1.put("maxSystolicValue",ObjectUtil.isNotEmpty(healthReportCountMap.get("max_systolic_value"))? healthReportCountMap.get("max_systolic_value"):0 );
        map1.put("avgSystolicValue",ObjectUtil.isNotEmpty(healthReportCountMap.get("avg_systolic_value"))? healthReportCountMap.get("avg_systolic_value"):0 );
        map1.put("minDiastolicValue",ObjectUtil.isNotEmpty(healthReportCountMap.get("min_diastolic_value"))? healthReportCountMap.get("min_diastolic_value"):0 );
        map1.put("maxDiastolicValue",ObjectUtil.isNotEmpty(healthReportCountMap.get("max_diastolic_value"))? healthReportCountMap.get("max_diastolic_value"):0 );
        map1.put("avgDiastolicValue",ObjectUtil.isNotEmpty(healthReportCountMap.get("avg_diastolic_value"))? healthReportCountMap.get("avg_diastolic_value"):0 );
        return map1;
    }
}
